from __future__ import annotations
from typing import Optional, NamedTuple
from collections import UserList
from enum import Enum
from abc import ABC

# Item = NamedTuple('Item', [('item_name', str), ('item_tags', frozenset[str])])

class Item:
    def __init__(self, item_name: str, item_tags: frozenset[str] = frozenset(), item_categorys: frozenset[str] = frozenset()) -> None:
        self.name = item_name
        self.tags = item_tags
        self.categorys = item_categorys

    def __str__(self) -> str:
        return self.name

    def __hash__(self) -> int:
        return hash(self.name)

    def __eq__(self, other) -> bool:
        if isinstance(other, Item):
            if self.name == other.name:
                return True
        return False

    def __lt__(self, other) -> bool:
        if isinstance(other, Item):
            return self.name < other.name
        else:
            raise TypeError(f'cant compare Item with {type(other)}')

    def __gt__(self, other) -> bool:
        if isinstance(other, Item):
            return self.name > other.name
        else:
            raise TypeError(f'cant compare Item with {type(other)}')


class Item_Factory:
    def __init__(self):
        self.item_name_map: dict[str, Item] = {}

    def get_item(self, item_name: str, item_tags: frozenset[str]) -> Item:
        if item_name in self.item_name_map:
            item = self.item_name_map[item_name]
        else:
            item = Item(item_name, item_tags)
            self.item_name_map[item_name] = item
        return item


class Record(UserList):
    def __init__(self, weight: int = 1) -> None:
        self.weight = weight
        self.data: list[Item] = []

    def unique(self) -> Record:
        self.data = list(set(self.data))
        return self

    def ordered(self, item_frequency: dict[Item, int]) -> Record:
        self.data = sorted(self.data, key = lambda x: (item_frequency[x], x.name), reverse = True)
        return self

    def filter(self, item_frequency: dict[Item, int], threshold: int) -> Record:
        self.data = [item for item in self.data if item_frequency[item] >= threshold]
        return self

# flow

class DataSetType(Enum):
    Raw = 0
    Mapped = 1
    OneHot = 2
    FPTree = 3

class Adapter:
    pass

##　data -> different types
## type